package com.instalinks.android.apps.smspostservice.helper;

import java.util.Hashtable;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;

import com.instalinks.android.apps.smspostservice.R;
import com.instalinks.android.lib.AppHelper;
import com.instalinks.android.lib.ApplicationNotifications;
import com.instalinks.android.lib.Config;
import com.instalinks.android.lib.LibConstants;
import com.instalinks.android.lib.PhoneAttributes;
import com.instalinks.android.lib.UrlData;
import com.instalinks.android.lib.UrlResponse;
import com.instalinks.android.lib.UrlResponse.UrlResponseType;
import com.instalinks.android.lib.enums.DeviceType;
import com.instalinks.android.lib.enums.NetworkType;
import com.instalinks.android.lib.enums.PhoneParams;

public class AppConfig extends Config {

	private PhoneAttributes mPhoneAttr;

	public AppConfig(Context context) {
		super(context, Constants.CONFIG_FILE_NAME, false);

		this.rePopulate();
	}

	public String getAppUrl() throws Exception {
		try {
			UrlData urlData = new UrlData(LibConstants.Url.APP_CONFIG_URL,
					25000);

			Hashtable<String, String> htParams = new Hashtable<String, String>();

			htParams.put(ConfigParams.appid.toString(),
					this.mContext.getPackageName());

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				String url = response.getMessage();
				url = url.replace("\n", "");
				try {
					this.setDataPostUrl(url);
				} catch (Exception e) {
				}
				return url;// response.getMessage();
			} else {
				throw new Exception(
						"Error getting application data post url. Try reopening the application");
			}
		} catch (Exception e) {
			throw e;
		}
	}

	public ApplicationNotifications getExternalNotificationInstance() {
		ApplicationNotifications appNotif = new ApplicationNotifications(
				mContext, Constants.EXTERNAL_NOTIFICATION_ID,
				Constants.NOTIFICATION_TITLE, R.drawable.external_notification,
				isNotificationSoundFlag(), true);

		return appNotif;
	}

	public Hashtable<String, String> getDataPostHashtable() {
		Hashtable<String, String> htParams = new Hashtable<String, String>();

		htParams.put(ConfigParams.appid.toString(), mContext.getPackageName());
		htParams.put(ConfigParams.scode.toString(), getScode());
		htParams.put(PhoneParams.subid.toString(), getSubscriberId());
		htParams.put(PhoneParams.deviceid.toString(), getDeviceId());
		htParams.put(PhoneParams.email.toString(), getEmail());

		return htParams;
	}

	public boolean updateConfigFromHost() {
		try {
			this.rePopulate();

			if (getDataPostUrl().length() == 0) {
				getAppUrl();
			}

			UrlData urlData = new UrlData(getDataPostUrl());

			Hashtable<String, String> htParams = getDataPostHashtable();

			htParams.put(ConfigParams.mode.toString(),
					ConfigParams.modes.getconfig.toString());

			UrlResponse response = urlData.postData(htParams);
			if (response.getResponseType() == UrlResponseType.success) {
				return updateConfig(response.getMessage());
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public boolean sendConfigToHost(String urld, String failMessage, boolean gprs) {
		try {
			UrlData urlData = new UrlData(getDataPostUrl());

			Hashtable<String, String> htParams = getDataPostHashtable();

			htParams.put(ConfigParams.mode.toString(),
					ConfigParams.modes.setconfig.toString());

			htParams.put(ConfigParams.urld.toString(), urld);
			htParams.put(ConfigParams.fail_msg.toString(), failMessage);

			htParams.put(ConfigParams.gprs.toString(), String.valueOf(gprs));

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				return updateConfigFromHost();
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public void alert(String message) {
		AppHelper.alert(mContext, message);
	}

	/**
	 * Wakeup Lock
	 * 
	 * @param timeout
	 *            timeout in milliseconds
	 */
	public void wakeUp(long timeout) {
		AppHelper.wakeUp(mContext, timeout);
	}

	public final boolean isBaseServiceRunning() {
		ActivityManager manager = (ActivityManager) mContext
				.getSystemService(Context.ACTIVITY_SERVICE);
		for (RunningServiceInfo srv : manager
				.getRunningServices(Integer.MAX_VALUE)) {
			if (srv.service.getClassName().equals(
					"com.instalinks.android.apps.service.AppService")) {
				return true;
			}
		}
		return false;
	}

	public void rePopulate() {
		super.rePopulate();

		getPhoneAttributesInstance().resetAllAttributes();
	}

	private boolean updateConfig(String rawConfig) {

		if (rawConfig.toLowerCase().startsWith("error")) {
			return false;
		}

		String[] allCfg = rawConfig.split(";");

		for (String keyValues : allCfg) {
			String[] keyValue = keyValues.replace("\n", "").split("=");

			try {
				setValue(keyValue[0], keyValue[1]);
			} catch (Exception e) {
				return false;
			}
		}

		try {
			setValue(PhoneParams.subid.toString(), getSubscriberId());
		} catch (Exception e) {
			return false;
		}

		try {
			setValue(PhoneParams.deviceid.toString(), getDeviceId());
		} catch (Exception e) {
			return false;
		}

		this.rePopulate();
		return true;
	}

	private PhoneAttributes getPhoneAttributesInstance() {
		if (mPhoneAttr == null)
			mPhoneAttr = new PhoneAttributes(mContext);
		return mPhoneAttr;
	}

	public ServiceStartStatus allGoodToRunService() {

		if (!isAppUpToDate())
			return ServiceStartStatus.NewUpdateAvailable;
		else if (isPaidFlag() && !isValidFlag())
			return ServiceStartStatus.SubscriptionExpired;
		else if (!isPaidFlag() && !isValidFlag())
			return ServiceStartStatus.DemoLimitation;
		else if (!isValidDataNetwork())
			return ServiceStartStatus.ConnectivityFailure;
		else if (is2GNetwork() && !isGprsFlag())
			return ServiceStartStatus.GprsNotAllowed;
		else
			return ServiceStartStatus.Ok;
	}

	public void handleServiceResponse(ServiceStartStatus status) {
		switch (status) {
		case ConnectivityFailure:
			alert(mContext.getString(R.string.network_error));
			break;
		case IssueUpdatingConfigFile:
			alert(mContext.getString(R.string.config_download_error));
			break;
		case GprsNotAllowed:
			alert(mContext.getString(R.string.gprs_edge_not_allowed));
			break;
		case WifiRequired:
			alert(mContext.getString(R.string.wifi_required));
			break;
		case Non2gNetworkRequired:
			alert(mContext.getString(R.string.non2gnetworkrequired));
			break;
		case SubscriptionExpired:
			alert(mContext.getString(R.string.subscription_expired));
			break;
		case DemoLimitation:
			alert(mContext.getString(R.string.demo_limitation));
			break;
		case UnknownIssueStartingSmsService:
			alert("Unkown Issue Starting SMS Service");
			break;
		case NewUpdateAvailable:
			checkUpdates();
			break;
		case Started:
		case Ok:
			break;
		}
	}

	public boolean isAppUpToDate() {
		return true;
	}

	public void checkUpdates() {
		if (isAppUpToDate()) {
			alert("Application is up-to-date");
		} else {
			alert("New version of app is available for download.");
		}
	}

	public final boolean checkForDemoVersion() {
		rePopulate();
		ServiceStartStatus status = allGoodToRunService();
		if (status == ServiceStartStatus.SubscriptionExpired
				|| status == ServiceStartStatus.DemoLimitation) {
			try {
				setSmsServiceStatus(false);
			} catch (Exception e) {
			}

			handleServiceResponse(status);
			return false;
		}
		return true;
	}

	// /////////////////////////////////////////////////////////////////////

	public boolean isSmsServiceRunning() {
		return getBooleanValue(ConfigParams.sms_service.toString());
	}

	public void setSmsServiceStatus(boolean value) throws Exception {
		setBooleanValue(ConfigParams.sms_service.toString(), value);
	}

	// *************************
	public boolean isSubscribedFlag() {
		return getBooleanValue(ConfigParams.subscribed.toString());
	}

	public void setSubscribedFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.subscribed.toString(), value);
	}

	// *************************
	public boolean isGprsFlag() {
		return getBooleanValue(ConfigParams.gprs.toString());
	}

	public void setGprsFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.gprs.toString(), value);
	}

	// *************************
	public boolean isAutoReplyFlag() {
		return getBooleanValue(PhoneParams.autoreply.toString());
	}

	public void setAutoReplyFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.autoreply.toString(), value);
	}

	// *************************
	public boolean isMarkAsReadFlag() {
		return getBooleanValue(PhoneParams.mark_as_read.toString());
	}

	public void setMarkAsReadFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.mark_as_read.toString(), value);
	}

	// *************************
	public int getSmsSuccessCount() {
		return getIntValue(ConfigParams.smssuccesscount.toString());
	}

	public void setSmsSuccessCount(int count) throws Exception {
		setIntValue(ConfigParams.smssuccesscount.toString(), count);
	}

	// *************************
	public int getWebSmsCount() {
		return getIntValue(ConfigParams.websmscount.toString());
	}

	public void setWebSmsCount(int count) throws Exception {
		setIntValue(ConfigParams.websmscount.toString(), count);
	}

	// *************************
	public int getSmsInvalidCount() {
		return getIntValue(ConfigParams.smsinvalidcount.toString());
	}

	public void setSmsInvalidCount(int count) throws Exception {
		setIntValue(ConfigParams.smsinvalidcount.toString(), count);
	}

	// *************************
	public int getSmsDroppedCount() {
		return getIntValue(ConfigParams.smsdroppedcount.toString());
	}

	public void setSmsDroppedCount(int count) throws Exception {
		setIntValue(ConfigParams.smsdroppedcount.toString(), count);
	}

	// *************************
	public int getSmsFailedCount() {
		return getIntValue(ConfigParams.smsfailedcount.toString());
	}

	public void setSmsFailedCount(int count) throws Exception {
		setIntValue(ConfigParams.smsfailedcount.toString(), count);
	}

	// *************************
	public String getSubscriberIdFromConfig() {
		return getValue(PhoneParams.subid.toString());
	}

	public void setSubscriberIdFromConfig(String value) throws Exception {
		setValue(PhoneParams.subid.toString(), value);
	}

	// *************************
	public String getDataPostUrl() {
		return getValue(ConfigParams.app_url.toString());
	}

	public void setDataPostUrl(String url) throws Exception {
		setValue(ConfigParams.app_url.toString(), url);
	}

	// *************************
	public String getDestination() {
		return getValue(ConfigParams.destination.toString());
	}

	public void setDestination(String value) throws Exception {
		setValue(ConfigParams.destination.toString(), value);
	}

	// *************************
	public String getVersion() {
		return getValue(ConfigParams.version.toString());
	}

	public void setVersion(String version) throws Exception {
		setValue(ConfigParams.version.toString(), version);
	}

	// *************************
	public int getFreeCount() {
		return getIntValue(ConfigParams.freecount.toString());
	}

	public void setFreeCount(int count) throws Exception {
		setIntValue(ConfigParams.freecount.toString(), count);
	}

	// *************************
	public int getAvailableFreeCount() {
		return getIntValue(ConfigParams.availablefreecounts.toString());
	}

	public void setAvailableFreeCount(int count) throws Exception {
		setIntValue(ConfigParams.availablefreecounts.toString(), count);
	}

	// *************************
	public boolean isPaidFlag() {
		return getBooleanValue(ConfigParams.paid.toString());
	}

	public void setPaidFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.paid.toString(), value);
	}

	// *************************
	public boolean isAlphanumericSenderFlag() {
		return getBooleanValue(ConfigParams.allow_alphanumeric_sender
				.toString());
	}

	public void setAlphanumericSenderFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.allow_alphanumeric_sender.toString(),
				value);
	}

	// *************************
	public boolean isShortcodeSenderFlag() {
		return getBooleanValue(ConfigParams.allow_shortcode_sender.toString());
	}

	public void setShortcodeSenderFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.allow_shortcode_sender.toString(), value);
	}

	// *************************
	public boolean isWebSmsFlag() {
		return getBooleanValue(ConfigParams.allow_web_sms.toString());
	}

	public void setWebSmsFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.allow_web_sms.toString(), value);
	}

	// *************************
	public boolean isAutoStartOnBootFlag() {
		return getBooleanValue(PhoneParams.auto_start_on_boot.toString());
	}

	public void setAutoStartOnBootFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.auto_start_on_boot.toString(), value);
	}

	// *************************
	public boolean isNotificationSoundFlag() {
		if (!hasKey(PhoneParams.notification_sound.toString()))
			return true;

		return getBooleanValue(PhoneParams.notification_sound.toString());
	}

	public void setNotificationSoundFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.notification_sound.toString(), value);
	}

	// *************************
	public String getScode() {
		if (getValue(ConfigParams.scode.toString()).length() == 0)
			return "unk";
		else
			return getValue(ConfigParams.scode.toString());
	}

	public void setScode(String value) throws Exception {
		setValue(ConfigParams.scode.toString(), value);
	}

	// *************************
	public int getValidity() {
		return getIntValue(ConfigParams.validity.toString());
	}

	public void setValidity(int value) throws Exception {
		setIntValue(ConfigParams.validity.toString(), value);
	}

	// *************************
	public String getFailReplyMsg() {
		return getValue(ConfigParams.fail_msg.toString());
	}

	public void setFailReplyMsg(String value) throws Exception {
		setValue(ConfigParams.fail_msg.toString(), value);
	}

	// *************************

	public boolean isValidFlag() {
		if (isPaidFlag()) {
			int v = getValidity();
			return (v > 0);
		} else {
			return (getAvailableFreeCount() > 0);
		}
	}

	public String getValidityStatus() {
		if (isPaidFlag()) {
			int v = getValidity();
			return (v > 0 ? String.valueOf(v) + " Days"
					: "Subscription Expired");
		} else {
			return String.valueOf(getAvailableFreeCount()) + " of "
					+ String.valueOf(getFreeCount());
		}
	}

	public String getEmail() {
		return getPhoneAttributesInstance().primaryEmail;
	}

	public String getDeviceId() {
		return getPhoneAttributesInstance().deviceId;
	}

	public String getSubscriberId() {
		return getPhoneAttributesInstance().subscriberId;
	}

	public String getLocation() {
		return getPhoneAttributesInstance().location;
	}

	public String getBatteryStatus() {
		return getPhoneAttributesInstance().batteryStatus;
	}

	public String getSignalStrength() {
		return getPhoneAttributesInstance().signalStrength;
	}

	public boolean isConnectedToNetwork() {
		return getPhoneAttributesInstance().isConnected;
	}

	public NetworkType getNetworkType() {
		return getPhoneAttributesInstance().networkType;
	}

	public boolean isWifiNetwork() {
		return (getPhoneAttributesInstance().networkType == NetworkType.WiFi);
	}

	public boolean is3GNetwork() {
		return (getPhoneAttributesInstance().networkType == NetworkType.HSDPA || getPhoneAttributesInstance().networkType == NetworkType.UMTS);
	}

	public boolean is2GNetwork() {
		return (getPhoneAttributesInstance().networkType == NetworkType.GPRS || getPhoneAttributesInstance().networkType == NetworkType.EDGE);
	}

	public boolean isGSMDevice() {
		return (getPhoneAttributesInstance().deviceType == DeviceType.GSM);
	}

	public boolean isCDMADevice() {
		return (getPhoneAttributesInstance().deviceType == DeviceType.CDMA);
	}

	public String getDeviceType() {
		return getPhoneAttributesInstance().deviceType.toString();
	}

	public boolean isValidDataNetwork() {
		boolean result = (mPhoneAttr.networkType != NetworkType.UnknownNotConnected);
		return result;
	}

	public void resetCounters() {

		try {
			setSmsSuccessCount(0);
		} catch (Exception e) {
		}

		try {
			setSmsInvalidCount(0);
		} catch (Exception e) {
		}

		try {
			setSmsDroppedCount(0);
		} catch (Exception e) {
		}

		try {
			setSmsFailedCount(0);
		} catch (Exception e) {
		}

		try {
			setWebSmsCount(0);
		} catch (Exception e) {
		}
	}

	// *************************

}
